<?php
/**
 * @see Epic_Controller_Request_Http
 */
require 'Epic/Controller/Request/Http.php';
/**
 * @see Epic_Config_ini
 */
require 'Epic/Config/Ini.php';
/**
 * @see Epic_Controller_Action
 */
require 'Epic/Controller/Action.php';

/**
 * @category   Epic
 * @package    Epic_Controller
 * @author     Epic Core Team <nguyendnhat@gmail.com>
 */
class Epic_Controller_Front
{
	/**
     * Singleton instance
     * @var Epic_Controller_Front
     */
	private static $_instance = null;
	
	/**
     * Request object
     * @var Epic_Controller_Request_Abstract
     */
    private $_request = null;
	
	/**
     * Singleton instance
     *
     * @return Epic_Controller_Front
     */
	public static function getInstance() 
	{
        if (null === self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
	}
	
    /**
     * Enforce singleton; disallow cloning
     *
     * @return void
     */
    private function __clone() {}

    /**
     * Constructor
     *
     * Instantiate using {@link getInstance()}; Epic_Controller_Front is a singleton
     * object.
     *
	 * Route constructor used to set the necessary parameters
 	 * (module, controller, action) to the Request object
     *
     * @return void
     */
	private function __construct() 
	{
		$this->_request = new Epic_Controller_Request_Http();
		
		Epic::getRegistry()->set('config', Epic_Config_Ini::getInstance());
		
		Epic_Controller_Router_Route::getInstance()
			->setRequest($this->getRequest())
			->route();
	}
	
    /**
     * Retrieve request object
     *
     * @return Epic_Controller_Request_Abstract
     */
    public function getRequest()
    {
        return $this->_request;
    }

    /**
     * Retrieve the executed controller
     * 
     * @return string
     */
  	private function _getController() {
  		
    	return ucfirst($this->getRequest()->getControllerName()) . 'Controller';
 	}
 	
 	/**
     * Retrieve the executed action
     * 
     * @return string
     */
  	private function _getAction() 
  	{
    	return $this->getRequest()->getActionName() . 'Action';
  	}
	
	/*
	 * Initialize controller object and calls the action method for it
	 * 
	 * @return void
	 */ 
  	public function dispatch() {
  		require CORE_MODULE_DIR . ucfirst($this->getRequest()->getModuleName()) . DS . 'controllers' . DS . $this->_getController() . ".php";
  		
    	if(class_exists($this->_getController())) {
      		$objectController = new ReflectionClass($this->_getController()); // Usercontroler.php
      		
        	if($objectController->hasMethod($this->_getAction())) {
          		$controller = $objectController->newInstance($this->getRequest());
          		$method = $objectController->getMethod($this->_getAction());
          		$method->invoke($controller);
        	} else {
				 require 'Epic/Controller/Exception.php';
         		 throw new Epic_Controller_Exception('Action: ' . $this->_getAction() . ' not exists');
    		}
    	} else {
    		require 'Epic/Controller/Exception.php';
      		throw new Epic_Controller_Exception('Controller: ' . $this->_getController() . ' not exists');
    	}
  	}
}